package com.lee.commonerror.code.concurrent;

import com.lee.commonerror.common.annotation.Right;
import com.lee.commonerror.common.annotation.Wrong;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * {@link ThreadLocal}使用的坑
 * @author ：liylw
 * @date ：Created in 2021/4/9 18:09
 */
@RestController
@RequestMapping("threadLocalDemo")
public class ThreadLocalDemo {

    private final ThreadLocal<Integer> currentUser = ThreadLocal.withInitial(()->null);

    /**
     * 正常情况before 是null,after是这次的用户id
     * 但是有可能 before 不是null,而是某个之前请求的ID,这是因为Tomcat的用的是线程池.
     * 可以通过设置 server.tomcat.max-threads=1 快速复现
     *
     * @param userId
     * @return
     */
    @Wrong
    @GetMapping("wrong")
    public Map<String,String> wrong(@RequestParam("userId")Integer userId){

        String before = Thread.currentThread().getName() + ":" + currentUser.get();

        currentUser.set(userId);

        String after = Thread.currentThread().getName() + ":" + currentUser.get();

        Map<String,String > map = new HashMap<>();
        map.put("before",before);
        map.put("after",after);
        return map;
    }

    /**
     * 正确的是在方法完成后 在finally里显示的删除数据
     * @param userId
     * @return
     */
    @Right
    @GetMapping("right")
    public Map<String,String> right(@RequestParam("userId")Integer userId){

        String before = Thread.currentThread().getName() + ":" + currentUser.get();

        currentUser.set(userId);

        Map<String,String > map;
        try {
            String after = Thread.currentThread().getName() + ":" + currentUser.get();
            map = new HashMap<>();
            map.put("before",before);
            map.put("after",after);
        } finally {
            currentUser.remove();
        }
        return map;
    }
}
